﻿using IOP.SgrA;
using IOP.SgrA.SilkNet.Vulkan;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace VkSample66
{
    [ModulePriority(ModulePriority.RenderGroup)]
    public class StarPipelineModule : VulkanModule, IVulkanRenderWapperModule
    {

        public StarPipelineModule()
        {
        }

        public VulkanRenderWapper RenderWapper { get; set; }

        protected override async Task Load(VulkanGraphicsManager graphicsManager)
        {
            graphicsManager.TryGetCamera("main", out Camera camera);

            var lDevice = graphicsManager.VulkanDevice;
            var pipeCache = lDevice.PipelineCache;
            var disapatcher = RenderWapper.GetRenderDispatcher<VulkanSwapchainRenderDispatcher>();
            var pass = disapatcher.GetSwapchainRenderPass();
            var area = RenderWapper.RenderArea;
            var basePath = AppContext.BaseDirectory;
            var shaders = Path.Combine(basePath, "Assets", "Shaders");
            graphicsManager.TryGetRenderGroup("MainRenderGroup", out IRenderGroup group);
            var mainGroup = group as PrimaryVulkanRenderGroup;
            VulkanShaderInfo[] infos = new VulkanSPVShaderInfo[]
            {
                new VulkanSPVShaderInfo(ShaderTypes.VertexShader, "starVert", new FileInfo(Path.Combine(shaders,"starVert.spv"))),
                new VulkanSPVShaderInfo(ShaderTypes.FragmentShader, "starFrag", new FileInfo(Path.Combine(shaders, "starFrag.spv")))
            };
            await Task.WhenAll(infos[0].LoadShader(), infos[1].LoadShader());
            JsonDocument json = await JsonDocument.ParseAsync(File.OpenRead(Path.Combine(shaders, "pipeline.json")));

            var starJson = json.RootElement.GetProperty("StarPipelineLayoutCreateOption").ToString();
            var starPipelineJson = json.RootElement.GetProperty("StarPipeline").ToString();
            GraphicsPipelineCreateOption pipelineOption = JsonSerializer.Deserialize<GraphicsPipelineCreateOption>(starPipelineJson);
            var starPipeline = graphicsManager.CreateEmptyPipeline($"Star")
                .BuildPipelineLayoutFromJson(null, starJson)
                .BuildGraphicsPipeline(mainGroup.RenderPass, pipeCache, infos, pipelineOption);
            var sCommand = lDevice.CreateCommandPool((device, option) =>
            {
                option.Flags = CommandPoolCreateFlags.CommandPoolCreateResetCommandBufferBit;
                option.QueueFamilyIndex = device.WorkQueues[0].FamilyIndex;
            }).CreateSecondaryCommandBuffer();
            var aspect = (float)area.Width / area.Height;
            var secondary = graphicsManager.CreateSecondaryVulkanRenderGroup("StarGroup", starPipeline)
                .Binding(mainGroup, sCommand, new VulkanSemaphore[0], new VulkanFence[0]);
            secondary.SetCamera(camera);
            secondary.CreateGroupRenderingAction((builder) => builder.UseMiddleware<StarGroupRenderingMiddleware>());
            secondary.CreateItemRenderingAction((builder) => builder.UseMiddleware<StarItemMiddleware>());
        }

        protected override Task Unload(VulkanGraphicsManager manager)
        {
            return Task.CompletedTask;
        }
    }
}
